import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { findParentByClassName } from '@/utils/utils';
import { Form, Input, message, Popconfirm, Row, Spin } from 'antd';
import { debounce } from 'lodash';
import styles from '@/pages/Recruitment/Interview/Record.less';
import cn from 'classnames';
import moment from 'moment';
import LimitInput from '@/components/LimitInput';
import { Icon } from '@/pages/Recruitment/components';
import RecordTagButton from '@/pages/Recruitment/Interview/Containers/RecordTagButton';
import { DividerContainer } from '@/molecules';
import { changeQuestionsOrder, deleteQuestion, saveAnswer, saveComment, saveQuestion } from '../../../service';
import { stepData } from './enum';

const SAVE_METHOD_MAPPING = {
    title: saveQuestion,
    answer: saveAnswer,
    comment: saveComment
};

const Toolbar = ({ children }) => {
    const style = { height: 40, marginBottom: 8 };
    return (
        <Row type="flex" align="middle" style={style}>
            {children}
        </Row>
    );
};

const Label = ({ value, colon = false }) => {
    const style = { lineHeight: '22px', fontWeight: 500, color: 'rgba(0,0,0,0.65)' };
    return <div style={style}>{value + (colon ? '：' : '')}</div>;
};

const firstUpper = word => word.replace(/^\S/, s => s.toUpperCase());

const editFlagName = type => `is${firstUpper(type)}Edit`;
const getPoint = obj => {
    let t = obj.offsetTop;
    // eslint-disable-next-line no-cond-assign,no-param-reassign
    while ((obj = obj.offsetParent)) {
        t += obj.offsetTop;
    }
    return t;
};

const RecordQuestion = memo((
    {
        form,
        value = [],
        onChange,
        getRecordState = () => null,
        arrangeId,
        disableButton,
        scrollWrapRef,
        disableAll
    }) => {
    const [formList, setFormList] = useState([]);
    const { getFieldDecorator, validateFields, getFieldValue } = form;
    const [loading, setLoading] = useState(false);
    const questionRef = useRef();
    const answerRef = useRef();
    const commentRef = useRef();
    const [tooltipPlacement, setTooltipPlacement] = useState('topLeft');
    const [guideStep, setGuideStep] = useState(0);
    const hasSelfQuestion = useMemo(() => formList.some(item => item.isEqual), [formList]);
    const userCode = useMemo(() => {
        const user = localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {};
        return user?.userCode;
    }, []);
    const [guideVisible, setGuideVisible] = useState(!localStorage.getItem(`talk_record_guide${userCode}`));
    useEffect(() => {
        setFormList(value);
    }, [value]);
    useEffect(() => {
        localStorage.setItem(`talk_record_guide${userCode}`, 'true');
    }, []);
    const genUUID = useCallback(
        (length = 14) =>
            Number(
                Math.random()
                    .toString()
                    .substr(3, length) + Date.now()
            ).toString(36),
        []
    );

    const onAddQuestion = () => {
        const newFormList = getFieldValue('interviewQuestions').slice();
        const newData = {
            isNew: true,
            isEqual: true,
            isTitleEdit: true,
            key: genUUID()
        };
        // 插入到自己问题后面
        let index = -1;
        // eslint-disable-next-line no-plusplus
        for (let i = 0; i < newFormList.length; i++) {
            if (!newFormList[i].isEqual) {
                index = i;
                break;
            }
            // 单面试官，无他人问题时，需要处理成往后push
            if (i === newFormList.length - 1) {
                index = newFormList.length;
            }
        }
        if (index === -1) {
            newFormList.unshift(newData);
        } else {
            newFormList.splice(index, 0, newData);
        }
        onChange(newFormList);
        setTimeout(() => {
            const questionItemIndex = index === -1 ? 0 : index;
            if (scrollWrapRef && scrollWrapRef.current) {
                const obj = findParentByClassName(scrollWrapRef.current, 'tab-scroll-context');
                const item = document.getElementsByClassName('.question-item')[questionItemIndex];
                if (obj && item) {
                    obj.scrollTop = getPoint(item) - getPoint(obj);
                }
            }
            if (questionRef.current) {
                questionRef.current.focus();
            }
        })
    };

    const forceFormCheck = () => {
        const interviewQuestion = getFieldValue('interviewQuestion').slice();
        form.setFieldsValue({
            // 用于强行让form能够再次检测interviewQuestion
            interviewQuestion: interviewQuestion
                ? interviewQuestion.map(item => ({
                    submitCheck: !item.submitCheck
                }))
                : []
        });
    };

    const onQuestionRecord = async (item, index) => {
        if (item[editFlagName('title')] || item.loading) return;
        const newFormList = formList.slice();
        if (!item.isRecord) {
            newFormList[index] = {
                ...newFormList[index],
                loading: true
            };
            onChange(newFormList);
            const recordState = await getRecordState(1);
            if ([0, 2].includes(recordState)) {
                message.error(
                    recordState === 0 ? '当前未开始录音，不可标记录音时间！' : '当前录音已结束，不可标记录音时间'
                );
                newFormList[index] = {
                    ...newFormList[index],
                    loading: false
                };
                onChange(newFormList);
                return;
            }
        }
        let answerTimes = item.answer && item.answer.answerTimes ? item.answer.answerTimes : [];
        if (item.isRecord) {
            const len = answerTimes.length;
            answerTimes[len - 1] = {
                ...answerTimes[len - 1],
                endTime: new Date().getTime()
            };
        } else {
            answerTimes.push({
                startTime: new Date().getTime()
            });
        }
        answerTimes = answerTimes.map((time, i) => ({
            ...time,
            sort: i + 1
        }));
        newFormList[index] = {
            ...newFormList[index],
            answer: {
                ...(newFormList[index].answer || {}),
                answerTimes
            },
            isRecord: !item.isRecord,
            loading: false
        };
        onChange(newFormList);
        forceFormCheck();
    };

    const onDeleteRecordTime = (item, index, listIndex) => {
        if (item.isRecord) {
            message.error('请先停止当前录音');
            return;
        }
        const newFormList = formList.slice();
        const { answer = {} } = newFormList[index];
        let { answerTimes = [] } = answer;
        answerTimes.splice(listIndex, 1);
        answerTimes = answerTimes.map((time, i) => ({
            ...time,
            sort: i + 1
        }));
        newFormList[index] = {
            ...newFormList[index],
            answer: {
                ...(newFormList[index].answer || {}),
                answerTimes
            }
        };
        onChange(newFormList);
    };

    const onDeleteQuestion = async i => {
        const lists = getFieldValue('interviewQuestions');
        const questionId = lists[i].id;
        if (questionId) {
            await deleteQuestion(questionId);
        }
        const newFormList = formList.slice();
        newFormList.splice(i, 1);
        onChange(newFormList);
    };

    // 编辑/取消编辑
    const handleToggleEdit = useCallback(
        (index, type) => {
            const newFormList = getFieldValue('interviewQuestions');
            const flagName = editFlagName(type);
            const oldItem = newFormList[index];
            const refs = {
                title: questionRef,
                answer: answerRef,
                comment: commentRef
            };
            newFormList[index] = {
                ...oldItem,
                [flagName]: !oldItem[flagName]
            };
            onChange(newFormList);
            setTimeout(() => {
                if (refs[type]?.current) {
                    refs[type].current.focus();
                }
            }, 0)
        },
        [onChange, questionRef, answerRef, commentRef]
    );

    // 确定
    const handleConfirm = useCallback(
        debounce((fieldName, index, type, isContent) => {
            const fieldValue = getFieldValue(fieldName);
            validateFields([fieldName], err => {
                if (!err) {
                    const newFormList = getFieldValue('interviewQuestions');
                    const questionId = newFormList[index].id;
                    const params = isContent
                        ? {
                            questionId,
                            content: fieldValue,
                            id: newFormList[index][type]?.id
                        }
                        : { questionId, [type]: fieldValue, seq: index + 1 };
                    setLoading(true);
                    SAVE_METHOD_MAPPING[type]({ arrangeId, ...params }).then(res => {
                        setLoading(false);
                        const id = res.data;
                        // 赋值方式区分
                        let nextValue = { [type]: fieldValue, id };

                        // 根据这个判断是不是对象（answer,comment）
                        if (isContent) {
                            nextValue = {
                                [type]: {
                                    ...(newFormList[index][type] || {}),
                                    [type]: fieldValue,
                                    id
                                }
                            };
                        }
                        newFormList[index] = {
                            ...newFormList[index],
                            ...nextValue,
                            [editFlagName(type)]: false
                        };
                        onChange(newFormList);
                        forceFormCheck();
                    });
                }
            });
        }, 400),
        [onChange]
    );

    // 头部 编辑中
    const renderEditingTitle = useCallback(
        (item, index) => (
            <>
                {index + 1}.
                <Form.Item
                    style={{ width: '100%' }}
                >
                    {getFieldDecorator(`title_${item.id || item.key}`, {
                        initialValue: item.title || '',
                        rules: [
                            { required: true, message: '请输入自定义问题标题!', whitespace: true },
                            { max: 100, message: '自定义问题不能超过100个字符' }
                        ]
                    })(<Input
                        disabled={disableAll}
                        style={{ marginLeft: '10px' }}
                        autoComplete="off"
                        ref={questionRef}
                        onBlur={() => {
                            handleConfirm(`title_${item.id || item.key}`, index, 'title');
                        }}
                        onPressEnter={() => {
                            handleConfirm(`title_${item.id || item.key}`, index, 'title');
                        }}
                    />)}
                </Form.Item>
            </>
        ),
        [disableAll]
    );

    // 头部 浏览中
    const renderBrowsingTitle = useCallback(
        (item, index) => {
            const { title, createUserInfo = {}, isEqual } = item || {};
            const { employeeName } = createUserInfo;
            return (
                <div
                    className={styles.questionHeaderContent}
                >
                    <div className={styles.questionHeaderTitleWrap}>
                        <span className={styles.orderNo}>{index + 1}.</span>
                        <div
                            className={cn(styles.questionTitleContent, { [styles.questionTitleContentEdit]: isEqual })}
                            onClick={() => {
                                if (isEqual) handleToggleEdit(index, 'title');
                            }}
                        >
                            <span className={styles.questionTitle}>{title}</span>
                            {
                                isEqual && <i className={cn('iconfont', 'iconlistfunction_edit_icon_default', styles.questionEditIcon)} />
                            }
                        </div>
                    </div>
                    {employeeName && (
                        <span className={styles.questionCreateWrap}>
                            <i className={cn('iconfont', 'iconPeople_F', styles.createUserIcon)} />
                            <span className={styles.light}>{employeeName}</span>
                        </span>
                    )}
                </div>
            );
        },
        []
    );

    // 头部
    const renderTitle = useCallback(
        (item, index) => {
            if (item[editFlagName('title')]) {
                return renderEditingTitle(item, index);
            }
            return renderBrowsingTitle(item, index);
        },
        [renderEditingTitle, renderBrowsingTitle]
    );

    // 录音按钮
    const renderRecordButton = useCallback(
        (item, index) => {
            if (!item.isEqual || disableButton) {
                return null;
            }
            const { isTitleEdit, loading: itemLoading, isRecord } = item || {};
            let classes = cn(styles.questionRecordButtonIconWrap, {
                [styles.unQuestionRecordBtnIcon]: isTitleEdit
            });
            if (isRecord) {
                classes = styles.questionRecordButtonIconing;
            }
            return (
                <div style={{ display: 'inline-flex' }}>
                    <RecordTagButton
                        params={{
                            item,
                            index,
                            classes,
                            isRecord,
                            onQuestionRecord,
                            loading: itemLoading
                        }}/>
                </div>
            );
        },
        [onQuestionRecord]
    );

    // 录音内容
    const renderRecordContent = useCallback(
        (item, index) => {
            const { answer } = item || {};
            if (!answer?.answerTimes?.length) {
                return null;
            }
            return answer.answerTimes.map((l, i) => l.startTime && l.endTime ? (
                <div key={l.startTime} className={styles.questionRecordDateItem}>
                    <div className={styles.questionRecordDateItemWrap}>
                        <i className="iconfont iconlistfunciton_soundclip_icon_default" />
                        {`${moment(l.startTime).format('HH:mm:ss')} - ${
                            l.endTime ? moment(l.endTime).format('HH:mm:ss') : ''
                        }`}
                        {
                            !disableAll && <Popconfirm
                                getPopupContainer={trigger => trigger.parentNode}
                                title="确定删除此录音标记?"
                                onConfirm={() => {
                                    onDeleteRecordTime(item, index, i);
                                }}
                            >
                                <i className={cn('iconfont iconDeleteIcon', styles.questionRecordDeleteIcon)} />
                            </Popconfirm>
                        }
                    </div>
                </div>
            ) : <span/>);
        },
        [onDeleteRecordTime, disableAll]
    );

    // 回答 头部
    const renderAnswerToolbar = useCallback(
        (item, index) => {
            const { isEqual } = item;
            return (
                <div>
                    <Toolbar>
                        <div style={{ flex: 1 }}>
                            <Label value="答复" />
                        </div>
                        {renderRecordButton(item, index)}
                    </Toolbar>
                    {
                        isEqual &&
                        <div className={styles.questionRecordDateList}>{renderRecordContent(item, index)}</div>
                    }
                </div>
            );
        },
        [renderRecordButton, renderRecordContent]
    );

    // 回答 内容
    const renderAnswerContent = useCallback((item, index) => {
        const type = 'answer';
        const val = item?.[type]?.content ?? '';
        if (item?.isEqual) {
            return getFieldDecorator(`answer_${item.id || item.key}`, {
                initialValue: val,
                rules: [
                    { required: true, message: '请输入答复!', whitespace: true },
                    { max: 2000, message: '答复不能超过2000个字符' }
                ]
            })(
                <LimitInput
                    disabled={disableAll}
                    inputRef={answerRef}
                    area
                    maxLength={2000}
                    placeholder="请输入"
                    autoSize={{ minRows: 4, maxRows: 4 }}
                    onBlur={() => {
                        if (val === getFieldValue(`answer_${item.id || item.key}`)) return;
                        handleConfirm(`${type}_${item.id || item.key}`, index, type, true)
                    }}
                />
            );
        }
        return (
            <div className={styles.browsingContainer}>
                {val.split('\n').map(show => (
                    <span>{show}</span>
                ))}
            </div>
        );
    }, [handleToggleEdit, answerRef, disableAll]);

    // 回答
    const renderAnswer = useCallback(
        (item, index) => {
            const { isEqual, answer } = item || {};
            if (!isEqual && !answer?.content) {
                return null;
            }
            return (
                <Form.Item>
                    {renderAnswerToolbar(item, index)}
                    {renderAnswerContent(item, index)}
                </Form.Item>
            );
        },
        [renderAnswerToolbar, renderAnswerContent]
    );

    // 评论 头部
    const renderCommentToolbar = useCallback(
        () => (
            <>
                <Toolbar>
                    <Row type="flex" style={{ flex: 1 }} align="middle">
                        <Label value="评价" />
                    </Row>
                </Toolbar>
            </>
            ),
        []
    );

    // 评论 内容
    const renderCommentContent = useCallback((item, index) => {
        const type = 'comment';
        const val = item?.[type]?.content ?? '';
        return getFieldDecorator(`comment_${item.id || item.key}`, {
            initialValue: val,
            rules: [
                { required: item?.isEqual, message: '请输入评价!', whitespace: true },
                { max: 1000, message: '评价不能超过1000个字符' }
            ]
        })(<LimitInput
            disabled={disableAll}
            inputRef={commentRef}
            area
            maxLength={1000}
            autoSize={{ minRows: 4, maxRows: 4 }}
            placeholder="请输入"
            onBlur={() => {
                if (val === getFieldValue(`${type}_${item.id || item.key}`)) return;
                handleConfirm(`${type}_${item.id || item.key}`, index, type, true)
            }}
        />);
    }, [handleConfirm, handleToggleEdit, commentRef, disableAll]);

    // 评论
    const renderComment = useCallback(
        (item, index) => (
            <Form.Item>
                {renderCommentToolbar(item, index)}
                {renderCommentContent(item, index)}
            </Form.Item>
        ),
        [renderCommentToolbar, renderCommentContent]
    );

    // 重新记录数组顺序
    const reorder = (list, startIndex, endIndex) => {
        const result = Array.from(list);

        const [removed] = result.splice(startIndex, 1);

        result.splice(endIndex, 0, removed);
        return result;
    };

    const onMoveEnd = async (startIndex, endIndex) => {
        const items = reorder(
            formList,
            startIndex,
            endIndex
        );
        try {
            setLoading(true);
            const { code } = await changeQuestionsOrder({
                arrangeId,
                srcQuestionId: formList[startIndex]?.id,
                destQuestionId: formList[endIndex]?.id
            });
            if (code === 10000) {
                onChange(items);
            }
            setLoading(false);
        } catch (e) {
            setLoading(false);
            console.log(e);
        }
    };

    const renderOperateBtn = (item, index) => {
        const { isEqual, isNew, title } = item;
        if (isEqual && !disableAll) {
            const selfFormList = formList.filter(v => v.isEqual);
            const isMove = selfFormList.every(v => !!v.title);
            const Com = [];
            if (isEqual || isNew) {
                Com.push(<Popconfirm
                    getPopupContainer={trigger => trigger.parentNode}
                    overlayClassName={styles.PopconfirmCustomer}
                    title={
                        <div className={styles.PopconfirmCustomerContent}>
                            <div className={styles.PopconfirmCustomerTitle}>确定删除此自定义问题？</div>
                            {
                                title && <div className={styles.PopconfirmCustomerDec}>答复及评价将一并删除</div>
                            }
                        </div>
                    }
                    onConfirm={() => {
                        onDeleteQuestion(index);
                    }}
                >

                    <Icon
                        title="删除"
                        type="DeleteIcon"
                        className={styles.deleteIcon}
                    />
                </Popconfirm>)
            }
            if (isMove) {
                if (index !== 0) {
                    Com.push(<Icon
                        title="上移"
                        type="TopArrowIcon"
                        onClick={() => { onMoveEnd(index, index - 1) }}
                    />)
                }
                if (index !== selfFormList.length - 1) {
                    Com.push(<Icon
                        title="下移"
                        type="DownArrowIcon"
                        onClick={() => { onMoveEnd(index, index + 1) }}
                    />)
                }
            }
            return <DividerContainer className={cn(styles.questionBtnWrap, { [styles.questionBtnWrapShow]: guideVisible && index === 0 })} type="horizontal" dividerProps={{ style: { margin: '16px auto', minWidth: 12, width: 12 } }}>
                {Com}
            </DividerContainer>
        }
        return null
    };

    const CustomPopconfirm = useCallback(({ children }) => <Popconfirm
        overlayClassName={cn(styles.guideWrap, 'talk-guide-Popconfirm')}
        cancelText={stepData?.[guideStep]?.isJump ? '跳过' : ' '}
        okType="link"
        cancelType="link"
        icon={null}
        autoAdjustOverflow={false}
        okText={stepData[guideStep]?.continueText}
        title={<div>
            <div style={{ fontWeight: 500, marginBottom: 4, fontSize: 14 }}>
                {stepData[guideStep]?.title}
            </div>
            <div style={{ color: 'rgba(0,0,0,0.45)' }}>{stepData[guideStep]?.msg}</div>
        </div>}
        visible={guideVisible}
        placement={tooltipPlacement}
        getPopupContainer={trigger => trigger.parentNode}
        onCancel={() => { setGuideVisible(false) } }
        onConfirm={() => {
                const step = guideStep + 1;
                const nextPlacement = stepData?.[guideStep]?.nextPlacement;
                setGuideStep(step);
                if (nextPlacement) {
                    setTooltipPlacement(nextPlacement);
                } else {
                    setGuideVisible(false);
                }
            }}
        >
        { children }
    </Popconfirm>, [guideStep, guideVisible]);

    const renderQuestion = (item, index) => <div className={styles.questionWrap}>
        <div className={styles.questionInfo}>
            <div className={styles.questionHeader}>
                {renderTitle(item, index)}
                {/* <span className={styles.questionHeaderContent}></span> */}
            </div>
            <div className={styles.questionContent}>
                {renderAnswer(item, index)}
                {renderComment(item, index)}
                <div
                    className={cn({ [styles.questionContentModal]: item[editFlagName('title')] })}
                    />
            </div>
        </div>
        { index === 0 && guideStep === 1
            ? <CustomPopconfirm>
                { renderOperateBtn(item, index) }
            </CustomPopconfirm>
            : renderOperateBtn(item, index)
        }
    </div>;

    return (
        <Spin spinning={loading}>
            {formList.map((item, index) => <div className={cn(styles.interviewQuestionFormItem, '.question-item')} key={item.id || item.key}>
                {
                        index === 0 && guideStep !== 1 && hasSelfQuestion && !disableAll
                            ? <CustomPopconfirm>
                                { renderQuestion(item, index) }
                            </CustomPopconfirm>
                            : renderQuestion(item, index)
                    }
                <Form.Item>
                    {
                            getFieldDecorator(`interviewQuestion[${index}].submitCheck`, {
                                validateTrigger: 'onSubmit', // 设置进行表单验证的时机为onSubmit
                                force: true,
                                rules: [
                                    {
                                        validator(_, interviewQuestion, callback) {
                                            const formItem = getFieldValue('interviewQuestions')?.[index];
                                            if (
                                                formItem?.[editFlagName('title')]
                                            ) {
                                                callback('请完成自定义问题编辑');
                                                return;
                                            }
                                            if (formItem?.isRecord) {
                                                callback('当前录音正在执行！');
                                                return;
                                            }
                                            callback();
                                        }
                                    }
                                ]
                            })(
                                <div/>
                            )
                        }
                </Form.Item>
            </div>)}
            <div className={styles.addQuestion} onClick={onAddQuestion}>
                + 添加问题
            </div>
        </Spin>
    );
});

export default RecordQuestion;
